package repo

import (
	"fmt"
	"os/exec"
	"strings"
	"time"
)

type EventName string

type DeviceEvent struct {
	Id       string    `json:"id"`
	DeviceId string    `json:"deviceId"`
	Name     EventName `json:"name"`
	Time     time.Time `json:"time"`
}

const (
	OnLine   EventName = "上线"
	DropLine EventName = "掉线"
)
const ThresholdSecond = 5

func makeDeviceEvent(dev *cacheDevice, name EventName) *DeviceEvent {
	return &DeviceEvent{
		Id:       dev.ID,
		DeviceId: dev.DeviceId,
		Name:     name,
		Time:     time.Now(),
	}
}

func LaunchMonitor(stopChan <-chan byte, eventChan chan<- *DeviceEvent) {
	stopChan2 := make(chan byte)
	go checkStaticOnline(stopChan2)

	ticker := time.NewTicker(2 * time.Second)
	for {
		select {
		case <-stopChan:
			stopChan2 <- 1
			return
		case <-ticker.C:
			for _, dev := range cacheMap {
				if dev.online && time.Now().Sub(dev.lastHeartbeatTime).Seconds() > ThresholdSecond {
					dev.online = false
					eventChan <- makeDeviceEvent(dev, DropLine)
					continue
				}
				if !dev.online && time.Now().Sub(dev.lastHeartbeatTime).Seconds() < ThresholdSecond {
					dev.online = true
					eventChan <- makeDeviceEvent(dev, OnLine)
				}
			}
		}
	}
}

func checkStaticOnline(stopChan <-chan byte) {
	ticker := time.NewTicker(3 * time.Second)
	for {
		select {
		case <-stopChan:
			return
		case <-ticker.C:
			for _, dev := range cacheMap {
				if !dev.IsDynamic && ping(dev.IP) {
					HeartbeatDevice(dev.DeviceId)
				}
			}
		}
	}
}

func ping(ip string) bool {
	Command := fmt.Sprintf("ping -c1 -w1 %s  > /dev/null && echo true || echo false", ip)
	output, err := exec.Command("/bin/sh", "-c", Command).Output()
	if err != nil {
		fmt.Println(err)
		return false
	}
	result := strings.TrimSpace(string(output))
	if result == "true" {
		return true
	}
	return false
}
